home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol242 / 6300clck.asm next >
Encoding:
Assembly Source File  |  1986-12-01  |  10.3 KB  |  294 lines

  1. ;************* EQUATES FOR THE ASSEMBLER ***************************************
  2.  
  3. KYBD_DATA     EQU     60H        ;KEYBOARD DATA PORT
  4. KYBD_CTL      EQU     61H        ;KEYBOARD CONTROL PORT
  5. KYBD_SEOI     EQU     61H        ;SPECIFIC END OF INTERRUPT CODE FOR
  6.                     ;  INT 09H KEYBOARD HARDWARE SERVICE
  7. PIC_CTL       EQU     20H        ;PIC CONTROL PORT
  8.  
  9. ;************* AN EXTRA SEGMENT ************************************************
  10.  
  11. SCREEN          SEGMENT AT 0B000H     ;EXTRA SEGMENT SO WE CAN WRITE
  12. SCREEN          ENDS            ; TO THE SCREEN.
  13.  
  14. ;************* THE CODE SEGMENT ************************************************
  15.  
  16. CODE_SEG      SEGMENT
  17.           ASSUME  CS:CODE_SEG
  18.           ORG     100H
  19.  
  20. FIRST:          JMP     LOAD_CLOCK    ;1ST TIME THRU, INITIALIZE.
  21.  
  22. ;------------- DATA DEFINITIONS ------------------------------------------------
  23.  
  24. MESSAGE       DB      ' '        ;THIS IS THE CLOCK DISPLAY.
  25. MSG_HOURS     DW      ?
  26.           DB      ':'
  27. MSG_MINUTES   DW      ?
  28.           DB      ':'
  29. MSG_SECONDS   DW      ?
  30.           DB      ' '
  31. AMPM          DB      ' '
  32.           DB      'M '
  33.  
  34. SCREEN_ATTR   DB      1EH        ;BRIGHT YELLOW ON CYAN
  35.  
  36. STATUS_PORT   DW      03BAH        ;VIDEO CONTROLLER STATUS PORT
  37.  
  38. CURR_HOUR     DB      ?         ;STORAGE FOR THE CURRENT TIME.
  39. CURR_MIN      DB      ?
  40. CURR_SEC      DB      ?
  41.  
  42. PREV_SEC      DB      ?
  43.  
  44. ON_OFF_FLAG   DB      1         ;PROGRAM ON/OFF TOGGLE FLAG
  45. KEY_WATCH     DB      0         ;ALT KEY DEPRESSED FLAG
  46. COUNTER       DB      0
  47. WORKING       DB      0         ;PGM IN PROGRESS FLAG.
  48.  
  49. FIRST_POSITION        DW       ?        ;POS OF 1ST CHAR ON SCREEN.
  50. SCREEN_SEG_OFFSET   DW       0        ;0 FOR MONO, 8000H FOR COLOR.
  51. OLD_TIMER_INT        DD       ?        ;LOC OF OLD TIMER INTERRUPT ROUTINE.
  52. OLD_INT09H        DD       ?        ;LOC OF OLD KYBD I/O INTERRUPT
  53.  
  54. ;-------------------------------------------------------------------------------
  55.  
  56. CLOCK          PROC    FAR        ;THE TIMER INTERRUPT WILL NOW
  57.           ASSUME  CS:CODE_SEG    ; COME HERE.
  58.  
  59.           STI            ;ALLOW HARDWARE INTERRUPTS.
  60.           CMP     WORKING,1     ;IS PROGRAM ALREADY RUNNING?
  61.           JNE     CHK_COUNTER    ; NO, CONTINUE.
  62.           JMP     FIN        ; YES, EXIT.
  63.  
  64. CHK_COUNTER:  INC     COUNTER        ;INCREMENT OUR COUNTER
  65.           CMP     COUNTER,3     ;ARE WE READY TO RUN?
  66.           JNB     CHK_TOGGLE    ;YES, CONTINUE
  67.           JMP     FIN        ;NO, EXIT
  68.  
  69. CHK_TOGGLE:   CMP     ON_OFF_FLAG,1    ;SHOULD WE DO THE CLOCK?
  70.           JE      SAVE_OLD        ;YES, CONTINUE
  71.           JMP     FIN        ;NO, EXIT
  72.  
  73. SAVE_OLD:     MOV     WORKING,1
  74.           MOV     COUNTER,0
  75.           PUSH    AX        ;SAVE USED REGISTER
  76.           PUSH    BX        ;SAVE USED REGISTERS.
  77.           PUSH    CX
  78.           PUSH    DX
  79.           PUSH    SI
  80.           PUSH    DI
  81.           PUSH    ES
  82.  
  83. GET_TIME:     MOV     AH,-2        ;GET TICKS OF BIOS TIMER.
  84.           INT     1AH        ;CX=HIGH COUNT, DX=LOW COUNT.
  85.           MOV     CURR_HOUR,CH
  86.           MOV     CURR_MIN,CL
  87.           MOV     CURR_SEC,DH
  88.  
  89. CHECK_PREV:   CMP     DH,PREV_SEC    ;TIME TO UPDATE DISPLAY?
  90.           JNE     UPDATE_PREV    ; YES, RUN WITH IT
  91.           JMP     RESET_OLD     ; NO, EXIT
  92.  
  93. UPDATE_PREV:  MOV     PREV_SEC,DH    ;UPDATE PREVIOUS SECOND FIELD
  94.  
  95. CHECK_AMPM:   CMP     CURR_HOUR,12    ;ARE WE IN AM OR PM TIME?
  96.           JB      AM_HOUR        ; IF HOURS<12, IT'S AM
  97.           JZ      NOON        ; IF HOURS=12 IT'S NOON, DISPLAY A 12
  98.           SUB     CURR_HOUR,12    ; OTHERWISE, IT'S PM.
  99. NOON:          MOV     AMPM,'P'        ;SET PM FLAG.
  100.           JMP     CREATE_MSG
  101.  
  102. AM_HOUR:      MOV     AMPM,'A'        ;SET AM FLAG.
  103.           CMP     CURR_HOUR,0    ;IS IT MIDNIGHT?
  104.           JNE     CREATE_MSG    ; NO, CONTINUE.
  105.           MOV     CURR_HOUR,12    ; YES, DISPLAY A 12.
  106.  
  107. CREATE_MSG:   MOV     AL,CURR_HOUR    ;CONVERT HOURS TO ASCII.
  108.           CALL    BIN_TO_ASCII
  109.           MOV     MSG_HOURS,AX    ;MOVE HOURS TO MSG AREA.
  110.           MOV     AL,CURR_MIN    ;CONVERT MINUTES TO ASCII.
  111.           CALL    BIN_TO_ASCII
  112.           MOV     MSG_MINUTES,AX    ;MOVE MINUTES TO MSG AREA.
  113.           MOV     AL,CURR_SEC    ;CONVERT SECONDS TO ASCII.
  114.           CALL    BIN_TO_ASCII
  115.           MOV     MSG_SECONDS,AX    ;MOVE SECONDS TO MSG AREA.
  116.  
  117. SET_ES:       ASSUME  ES:SCREEN     ;SET ES TO POINT TO THE SCREEN.
  118.           MOV     DX,SCREEN
  119.           MOV     ES,DX
  120.  
  121. WRITE_MSG:    MOV     CX,13        ;WRITE 8 CHARACTERS.
  122.           MOV     SI,OFFSET MESSAGE    ;ADDRESS OF STRING TO MOVE.
  123.           MOV     DI,SCREEN_SEG_OFFSET
  124.           ADD     DI,FIRST_POSITION    ;DESTINATION ADDRESS FOR THE MOVE.
  125.           MOV     DX,STATUS_PORT    ;VIDEO STATUS PORT NUMBER
  126.           CLI            ;NO HARDWARE INTERRUPTS UNTIL DONE
  127.  
  128. WAIT_LOW_1:   IN      AL,DX        ;WAIT FOR SCAN STATUS TO GO LOW.
  129.           TEST    AL,1
  130.           JNZ     WAIT_LOW_1
  131. WAIT_HIGH_1:  IN      AL,DX        ;AFTER SCAN STATUS GOES LOW, IT MUST GO
  132.           TEST    AL,1        ; HIGH BEFORE WE CAN WRITE DIRECTLY TO
  133.           JZ      WAIT_HIGH_1    ; THE VIDEO BUFFER WITHOUT CAUSING SNOW.
  134.  
  135. WRITE_CHAR:   MOVS    ES:BYTE PTR[DI],CS:[SI]
  136.  
  137. WAIT_LOW_2:   IN      AL,DX        ;WAIT FOR SCAN STATUS TO GO LOW.
  138.           TEST    AL,1
  139.           JNZ     WAIT_LOW_2
  140. WAIT_HIGH_2:  IN      AL,DX        ;AFTER SCAN STATUS GOES LOW, IT MUST GO
  141.           TEST    AL,1        ; HIGH BEFORE WE CAN WRITE DIRECTLY TO
  142.           JZ      WAIT_HIGH_2    ; THE VIDEO BUFFER WITHOUT CAUSING SNOW.
  143.  
  144. WRITE_ATTR:   MOV     AL,SCREEN_ATTR    ;SCREEN ATTRIBUTE CHAR. TO USE
  145.           MOV     ES:[DI],AL
  146.           INC     DI
  147.           LOOP    WAIT_LOW_1
  148.           STI            ;OK TO ALLOW INTERRUPTS NOW.
  149.  
  150. RESET_OLD:    POP     ES        ;POP THE PUSHED REGISTERS.
  151.           POP     DI
  152.           POP     SI
  153.           POP     DX
  154.           POP     CX
  155.           POP     BX
  156.           POP     AX        ;POP THE PUSHED REGISTERS.
  157.           MOV     WORKING,0     ;RESET PGM IN PROGRESS FLAG.
  158.  
  159. FIN:          JMP     OLD_TIMER_INT    ;LET OLD ISR ISSUE THE IRET
  160.  
  161. CLOCK          ENDP
  162.  
  163. ;*******************************************************************************
  164.  
  165. BIN_TO_ASCII  PROC    NEAR
  166.  
  167. ;      THIS PROCEDURE CONVERTS A BINARY NUMBER IN AL INTO
  168. ;      2 ASCII CHARACTERS IN AX. THE LEAST SIGNIFIGANT BYTE IS
  169. ;      RETURNED IN AH, THE MOST SIGNIFICANT BYTE IN AL.
  170.  
  171.           PUSH    CX        ;SAVE USED REGISTER FOR POLITENESS.
  172.           XOR     AH,AH        ;ZERO OUT AH.
  173.           MOV     CL,10        ;DIVISOR FOR HEX TO DEC CONVERT.
  174.           DIV     CL        ;CONVERT AL TO DECIMAL QUOTIENT (TENS)
  175.                     ; REMAINDER GOES IN AH (ONES).
  176.           ADD     AL,30H        ;CONVERT AL TO ASCII.
  177.           ADD     AH,30H        ;CONVERT AH TO ASCII.
  178.           POP     CX        ;RESTORE PUSHED REGISTER.
  179.  
  180.           RET            ;RETURN TO CALLER.
  181. BIN_TO_ASCII  ENDP
  182.  
  183. ;*******************************************************************************
  184.  
  185. int09h          proc    far
  186. ;
  187. ; This procedure is used to service the keyboard hardware interrupt for
  188. ; the scrclock.com program.  It will check to see if the on/off trigger
  189. ; key has been pressed.  If it has, the on_off flag will be toggled.
  190. ;
  191.           assume  ds:nothing
  192.           sti
  193.           push    ax        ;save the used register
  194.  
  195. get_scan:     in      al,kybd_data    ;get a byte from kybd data port
  196.           cmp     al,38h        ;alt key "make"?
  197.           jne     alt_break     ;no, check for "break"
  198.           mov     key_watch,1    ;set alt key flag
  199.           jmp     int_service    ;and jump to the original isr
  200.  
  201. alt_break:    cmp     al,0b8h        ;alt key "break"?
  202.           jne     chk_watch     ;no, go check alt key flag
  203.           mov     key_watch,0    ;clear alt key flag
  204.           jmp     int_service    ;and jump to original isr
  205.  
  206. chk_watch:    cmp     key_watch,1    ;alt key flag set?
  207.           jne     int_service    ;no, jump to original isr
  208.  
  209. d_make:       cmp     al,20h        ;d key "make"?
  210.           jne     d_break        ;no, check for d key "break"
  211.           xor     on_off_flag,01h    ;toggle the clock
  212.           jmp     reset_kybd    ;go reset the keyboard
  213.  
  214. d_break:      cmp     al,0a0h        ;d key "break"?
  215.           je      reset_kybd    ;yes, reset the keyboard
  216.  
  217. int_service:  pop     ax        ;pop the pushed register
  218.           jmp     old_int09h    ;let original routine issue the iret
  219.  
  220. reset_kybd:   in      al,kybd_ctl    ;reset keyboard status
  221.           push    ax        ;then iret back to caller
  222.           or      al,80h
  223.           out     kybd_ctl,al
  224.           pop     ax
  225.           out     kybd_ctl,al
  226.           cli            ;disable interrupts
  227.           mov     al,kybd_seoi    ;send a "specific end of interrupt"
  228.           out     pic_ctl,al    ;to the pic controller chip
  229.           sti            ;re-enable interrupts
  230.           pop     ax
  231.           iret
  232.  
  233. int09h          endp
  234.  
  235.  
  236. ;*******************************************************************************
  237.  
  238. LOAD_CLOCK    PROC    NEAR        ;THIS PROC INITIALIZES EVERYTHING.
  239.  
  240. SCREEN_SETUP: MOV     AH,15        ;ASK FOR SERVICE 15 OF INT 10H.
  241.           INT     10H        ;TELLS HOW DISPLAY IS SET UP.
  242.           SUB     AH,13        ;MOVE TO 13 PLACES BEFORE EDGE.
  243.           SHL     AH,1        ;MULT. BY 2 (CHAR & ATTR BYTES).
  244.           MOV     BYTE PTR FIRST_POSITION,AH  ;SET SCREEN CURSOR POSITION.
  245.           TEST    AL,4        ;IS IT A MONO SCREEN?
  246.           JNZ     GET_OLD_INT    ; YES - ADJUSTMENT NOT REQUIRED.
  247.           MOV     SCREEN_SEG_OFFSET,8000H  ; NO - SET UP FOR COLOR.
  248.           MOV     STATUS_PORT,03DAH
  249.  
  250. GET_OLD_INT:  MOV     AH,35H        ;GET VECTOR FUNCTION
  251.           MOV     AL,1CH        ;TIMER INTERRUPT NUMBER
  252.           INT     21H        ;CALL DOS
  253.           MOV     WORD PTR OLD_TIMER_INT,BX     ;STORE OFFSET
  254.           MOV     WORD PTR OLD_TIMER_INT[2],ES  ;STORE SEGMENT
  255.  
  256. SET_NEW_INT:  MOV     DX,OFFSET CLOCK    ;DS:DX IS NEW INTERRUPT ADDRESS.
  257.           MOV     AL,1CH        ;1CH IS THE INTERRUPT TO CHANGE.
  258.           MOV     AH,25H        ;DOS FUNCTION 25H TO RESET VECTOR.
  259.           INT     21H        ;CALL DOS.
  260.  
  261. GET_OLD_KYBD: MOV     AH,35H        ;GET VECTOR FUNCTION
  262.           MOV     AL,09H        ;KEYBOARD HARDWARE INTERRUPT
  263.           INT     21H        ;CALL DOS
  264.           MOV     WORD PTR OLD_INT09H,BX     ;SAVE OFFSET
  265.           MOV     WORD PTR OLD_INT09H[2],ES  ;SAVE SEGMENT
  266.  
  267. SET_NEW_KYBD: MOV     DX,OFFSET INT09H    ;OFFSET OF NEW KYBD I/O INTERR.
  268.           MOV     AH,25H        ;DS ALREADY SET. AH=SET VECTOR.
  269.           MOV     AL,09H        ;INT. NUMBER TO SET - KYBD I/O
  270.           INT     21H        ;CALL DOS
  271.  
  272. LOAD_MSG:     MOV     DX,OFFSET INSTALLED$
  273.           MOV     AH,09
  274.           INT     21H        ;DISPLAY MESSAGE.
  275.  
  276. EXIT:          MOV     DX,OFFSET LOAD_CLOCK
  277.           INT     27H        ;EXIT - REMAIN RESIDENT.
  278.  
  279. LOAD_CLOCK    ENDP
  280.  
  281. ;-------------------------------------------------------------------------
  282.  
  283. INSTALLED$    DB      0AH,0DH,0AH,0DH,10 DUP(' ')
  284.           DB      'Screen Clock has been installed.',0DH,0AH
  285.           DB      10 DUP(' ')
  286.           DB      'Press ALT-D to toggle on and off.',0DH,0AH,'$'
  287.  
  288. ;-------------------------------------------------------------------------
  289.  
  290. CODE_SEG      ENDS
  291.           END     FIRST
  292.  
  293. ;*******************************************************************************
  294.